import socket
import struct
import json
import time
import errno
import select

class TCPClient:
    def __init__(self, host='localhost', port=8080):
        self.host = host
        self.port = port
        self.socket = None
        self.connected = False
        self.timeout = 10
        
    def connect(self):
        """连接到TCP服务器"""
        try:
            if self.socket:
                self.socket.close()
                
            self.socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
            self.socket.settimeout(self.timeout)
            print(f"尝试连接到TCP服务器 {self.host}:{self.port}...")
            self.socket.connect((self.host, self.port))
            self.connected = True
            print(f"✅ 成功连接到TCP服务器 {self.host}:{self.port}")
            return True
        except socket.timeout:
            print("❌ 连接TCP服务器超时")
            return False
        except ConnectionRefusedError:
            print(f"❌ 连接被拒绝，请确保TCP服务器在 {self.host}:{self.port} 运行")
            return False
        except Exception as e:
            print(f"❌ 连接TCP服务器失败: {e}")
            return False
    
    def send_message(self, tag, value):
        """发送消息到TCP服务器"""
        if not self.connected or not self.socket:
            if not self.connect():
                return None
                
        try:
            # 构建消息
            value_bytes = value.encode('utf-8')
            length = len(value_bytes)
            
            print(f"📤 发送消息: tag={tag}, length={length}, value='{value}'")
            
            # 按照协议格式打包数据
            message = struct.pack('!II', tag, length) + value_bytes
            
            # 发送消息
            self.socket.sendall(message)
            print("✅ 消息发送成功")
            
            # 接收响应
            response = self.receive_message()
            return response
            
        except socket.timeout:
            print("❌ 发送消息超时")
            self.connected = False
            return None
        except BrokenPipeError:
            print("❌ 连接已断开")
            self.connected = False
            return None
        except Exception as e:
            print(f"❌ 发送消息失败: {e}")
            self.connected = False
            return None
            
    def receive_message(self):
        """接收TCP服务器的响应"""
        try:
            print("📥 开始接收响应...")
            
            # 设置接收超时
            self.socket.settimeout(30)
            
            # 接收消息头 (tag和length)
            header = self._receive_all(8)
            if header is None or len(header) < 8:
                print("❌ 头信息接收失败")
                return None
                
            tag, length = struct.unpack('!II', header)
            print(f"📋 解析头: tag={tag}, expected_length={length}")
            
            if length > 10 * 1024 * 1024:  # 10MB限制
                print(f"❌ 消息长度过大: {length}字节")
                return None
            
            # 接收消息体
            value_bytes = self._receive_all(length)
            if value_bytes is None:
                print("❌ 消息体接收失败")
                return None
                
            value = value_bytes.decode('utf-8')
            print(f"✅ 成功接收响应: length={len(value_bytes)}, value='{value[:100]}...'")
            
            return {
                'tag': tag,
                'length': length,
                'value': value
            }
            
        except socket.timeout:
            print("❌ 接收消息超时")
            return None
        except Exception as e:
            print(f"❌ 接收消息失败: {e}")
            return None
    
    def _receive_all(self, length):
        """接收指定长度的数据"""
        if not self.socket:
            return None
            
        data = b""
        remaining = length
        
        while remaining > 0:
            try:
                chunk = self.socket.recv(min(4096, remaining))
                if not chunk:
                    print("❌ 连接在接收数据过程中关闭")
                    return None
                    
                data += chunk
                remaining -= len(chunk)
                
            except socket.timeout:
                print(f"⏳ 接收超时，已接收 {len(data)}/{length} 字节")
                if len(data) == 0:
                    return None
                # 继续等待剩余数据
                continue
            except Exception as e:
                print(f"❌ 接收数据时发生错误: {e}")
                return None
                
        return data
            
    def close(self):
        """关闭连接"""
        if self.socket:
            try:
                self.socket.shutdown(socket.SHUT_RDWR)
            except:
                pass
            self.socket.close()
            self.socket = None
            self.connected = False
            print("🔌 TCP连接已关闭") 
